import sys,random
import json
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                            QHBoxLayout, QPushButton, QLineEdit, QListWidget, 
                            QLabel, QMessageBox,QDialog,QSlider, QLabel, QPushButton, QHBoxLayout)
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtCore import QUrl, pyqtSignal, pyqtSlot, QObject, Qt, QFile, QTextStream,QTimer
from PyQt6.QtWebEngineCore import QWebEngineScript

from sls_mainWindow import Ui_MainWindow
from PyQt6.QtWebChannel import QWebChannel
from sls_coordinationConvert import wgs84_to_gcj02
from  sls_mirrors import sls_UGVmirrorsUpdate,sls_agent,sls_UAVmirrorsUpdate
import numpy as np

from sls_ngc_uavDialog import UAVDialog
from sls_ngc_uavPPDialog import UAVPPDialog
from sls_ngc_ugvDialog import UGVDialog,UGVPathUploadDialog
from sls_ngc_orginDialog import OriginDialog, GPSRectifyDialog
from sls_ngc_serverselect import ServerSelectDialog
from sls_ngc_ugvPPDialog import UGVPPDialog

from sls_chat_float_ball import *
from sls_coordinationConvert import wgs84_to_gcj02,gcj02_to_wgs84
from sls_ngc_TOOLSDialog import TOOLSDialog
from energy_ball import EnergyBallWidget
from PyQt6.QtCore import QPropertyAnimation, QRect, QTimer


class NotifyClass():
    def __init__(self,parent):
        self.parent = parent
        self.notify_CordinateList = []

    def add_notify_Cordinate(self,func):
        self.notify_CordinateList.append(func)

    def notify_Cordinate(self,latitude,longitude):
        for item in self.notify_CordinateList:
            item(latitude,longitude)

    def remove_notify_Cordinate(self,func):
        self.notify_CordinateList.remove(func)   

class MapInteraction(QObject):
    def __init__(self, main_window):
        super().__init__()  # 调用父类 QObject 的构造函数
        self.main_window = main_window
        self.main_window:NGCMainWindow
    @pyqtSlot(float, float)
    def showCoordinates(self, latitude, longitude):

        longitude,latitude = gcj02_to_wgs84(longitude,latitude)
        #self.main_window.add_marker_gaode(latitude,longitude,"testpoint")
        #self.main_window.add_marker(latitude,longitude,"testpoint2")
        self.main_window.statusBar_signal.emit(f"点击位置坐标：{latitude}, {longitude}")
        self.main_window.notifyClass.notify_Cordinate(latitude,longitude)
    
    @pyqtSlot()
    def mapLoaded(self):
        self.main_window.statusBar_signal.emit(f"地图加载完成")
        self.main_window.mapLoadedFlag = True
        # 初始化浮动缩放控件
        self.main_window.init_zoom_widget()
        # lo,la = (119.502398,32.199149)
        # self.main_window.add_marker(la,lo,"testpoint")
        
    @pyqtSlot(float, float)
    def set_map_center(self, lng, lat):
        """设置地图中心坐标"""
        js_code = f"map.setCenter(new AMap.LngLat({lng}, {lat}));"
        # 直接使用已存储的main_window引用
        if hasattr(self.main_window, 'map_view'):
            self.main_window.map_view.page().runJavaScript(js_code)


class NGCMainWindow(QMainWindow):
    statusBar_signal = pyqtSignal(str)
    mapUpdate_signal = pyqtSignal(str)
    def __init__(self,selected_coordinates):
        super().__init__()
        # 初始化一些变量
        self.UAVaddedMarkerID = []
        self.UGVaddedMarkerID = []
        self.mapLoadedFlag = False
        self.selected_coordinates = selected_coordinates  # 在初始化时接收参数

        # 初始notifyClass
        self.notifyClass = NotifyClass(self)
        self.mapUpdate_signal.connect(self.map_update)

        # 初始化UI
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ScreenWidth = QApplication.primaryScreen().availableGeometry().width()
        # 链接状态信号到槽函数（状态条显示）
        self.statusBar_signal.connect(self.ui.statusbar.showMessage)

        # 创建 QWebEngineView 并添加到布局中
        self.map_view = QWebEngineView()
        self.map_view.setZoomFactor(2)
        self.ui.verticalLayout.addWidget(self.map_view)


        # 创建 QWebChannel 对象并注册 MapBridge
        self.web_channel = QWebChannel()
        self.map_interaction = MapInteraction(self)
        self.web_channel.registerObject('pybridge', self.map_interaction)

        # 创建悬浮球和聊天窗口（作为普通子控件）
        self.floating_ball = FloatingBall(self)
        ball_x = self.width() - 80
        ball_y = 600
        self.floating_ball.move(ball_x, ball_y)

        self.floating_ball.clicked.connect(self.toggle_chat_window)
        #添加右上角状态控制面板
        self.status_btn = QPushButton("🛰️ 状态", self)
        self.status_btn.resize(70, 25)
        self.status_btn.move(self.contentsRect().right()-70, self.contentsRect().top())

        self.status_btn.clicked.connect(self.toggle_status_panel)


        # 状态面板框
        self.status_frame = QFrame(self)
        self.status_frame.setGeometry(self.width() - 220, 50, 200, 0)
        self.status_frame.setMinimumHeight(0)
        self.status_frame.setMaximumHeight(500)
        self.status_frame.setStyleSheet("""
            QFrame {
                background-color: rgba(30, 30, 30, 230);
                border-radius: 10px;
            }
            QLabel {
                color: white;
                font-size: 13px;
            }
        """)

        layout = QVBoxLayout(self.status_frame)
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(6)

        title = QLabel("UAV / UGV 状态监控")
        title.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(title)

        # === UAV1 状态 ===
        self.label_uav1_title = QLabel("🛩 UAV1")
        self.label_uav1_lat = QLabel("纬度：--")
        self.label_uav1_lon = QLabel("经度：--")
        self.label_uav1_yaw = QLabel("航向角：--°")

        # === UAV2 状态 ===
        self.label_uav2_title = QLabel("🛩 UAV2")
        self.label_uav2_lat = QLabel("纬度：--")
        self.label_uav2_lon = QLabel("经度：--")
        self.label_uav2_yaw = QLabel("航向角：--°")

        # === UGV 状态 ===
        self.label_ugv_title = QLabel("🚜 UGV1")
        self.label_ugv_lat = QLabel("纬度：--")
        self.label_ugv_lon = QLabel("经度：--")
        self.label_ugv_yaw = QLabel("航向角：--°")

        # === 能量球 ===
        self.energy_ball = EnergyBallWidget(percent=100)
        self.energy_ball.setFixedSize(100, 100)

        for w in [
            self.label_uav1_title, self.label_uav1_lat, self.label_uav1_lon, self.label_uav1_yaw,
            self.label_uav2_title, self.label_uav2_lat, self.label_uav2_lon, self.label_uav2_yaw,
            self.label_ugv_title, self.label_ugv_lat, self.label_ugv_lon, self.label_ugv_yaw
        ]:
            layout.addWidget(w)

        layout.addSpacing(8)
        layout.addSpacing(5)
        layout.addWidget(self.energy_ball, alignment=Qt.AlignmentFlag.AlignCenter)
        label_liquid = QLabel("💧 剩余液量")
        label_liquid.setAlignment(Qt.AlignmentFlag.AlignCenter)
        label_liquid.setStyleSheet("color: white; font-size: 12px;")
        layout.addWidget(label_liquid)
        layout.addSpacing(5)

        self.status_frame.setLayout(layout)

        # 动画控制
        self.is_expanded = False
        self.anim = QPropertyAnimation(self.status_frame, b"geometry", self)

        # 模拟液量变化（每2秒随机更新一次）
        self.random_timer = QTimer(self)
        self.random_timer.timeout.connect(self.update_liquid)
        self.random_timer.start(2000)

        # 设置WebChannel
        self.map_view.page().setWebChannel(self.web_channel)

        # 加载HTML内容
        self.load_map()
    

        #1.创建agent并启动连接
        self.local_host_mode = local_host_mode
        self.mirror_agent = sls_agent.MirrorsAgent(local_host_mode=self.local_host_mode)
        self.mirror_agent.connect()
        #2.创建mirror并添加到agent中
        uav_mirror1 = sls_agent.Mirror("uav1")
        uav_mirror2 = sls_agent.Mirror("uav2")
        ugv_mirror1 = sls_agent.Mirror("ugv1")
        #3.给mirror添加mirror_update
        uav_mirror1.add_mirror_updates(sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate,sls_UAVmirrorsUpdate.BasicStatusMirrorUpdate)
        uav_mirror2.add_mirror_updates(sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate,sls_UAVmirrorsUpdate.BasicStatusMirrorUpdate)
        ugv_mirror1.add_mirror_updates(sls_UGVmirrorsUpdate.UGVBasicPositionMirrorUpdate)
        #4
        self.mirror_agent.add_mirrors(uav_mirror1)
        self.mirror_agent.add_mirrors(uav_mirror2)
        self.mirror_agent.add_mirrors(ugv_mirror1)
        #5. 给相应的mirror_update添加notify函数
        self.mirror_agent.add_notify_func_to_mirror_update("uav1",sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate,self.showUAVMirrorPosition)
        self.mirror_agent.add_notify_func_to_mirror_update("uav2",sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate,self.showUAVMirrorPosition)
        self.mirror_agent.add_notify_func_to_mirror_update("ugv1",sls_UGVmirrorsUpdate.UGVBasicPositionMirrorUpdate,self.showUGVMirrorPosition)

        self.ui.pushButton_UAV1.clicked.connect(lambda checked,id = "uav1": self.uav_clicked(id,self.ui.pushButton_UAV1))
        self.ui.pushButton_UAV2.clicked.connect(lambda checked,id = "uav2": self.uav_clicked(id,self.ui.pushButton_UAV2))
        self.ui.pushButton_UGV.clicked.connect(lambda checked,id = "ugv1": self.ugv_clicked(id,self.ui.pushButton_UGV))

        self.ui.uavPathPlan.triggered.connect(self.uav_pathplan_triggered)
        self.ui.ugvPathPlan.triggered.connect(self.ugv_pathplan_triggered)
        self.ui.origin.triggered.connect(self.origin_triggered)
        self.ui.ugvPathUpload.triggered.connect(self.ugv_PathUpload_triggered)
        self.ui.GPSrectify.triggered.connect(self.ugv_GPSrectify_triggered)
        self.ui.serverselection.triggered.connect(self.serverselection_triggered)
        self.ui.tools.triggered.connect(self.tools_triggered)

    
    def load_map(self):
        """加载包含高德地图的HTML页面"""
        # 读取HTML文件
        file = QFile("getting-start.html")
        if not file.open(QFile.OpenModeFlag.ReadOnly | QFile.OpenModeFlag.Text):
            error_string = file.errorString()
            print(f"无法打开地图HTML文件，错误信息: {error_string}")
            return
        
        stream = QTextStream(file)
        html = stream.readAll()
        file.close()
        # 替换API密钥
        #html = html.replace("YOUR_AMAP_API_KEY", self.amap_key)

        lng, lat = self.selected_coordinates
        # 直接替换HTML中的初始中心坐标
        html = html.replace(
            "center:new AMap.LngLat(119.515293,32.199403),", 
            f"center:new AMap.LngLat({lng},{lat}),"
        )
        self.statusBar_signal.emit(f"地图初始位置设置为: 经度{lng}, 纬度{lat}")
        
        # 设置HTML内容
        self.map_view.setHtml(html,baseUrl=QUrl("qrc:/"))

    def add_marker(self, latitude, longitude, name):        
        longitude,latitude = wgs84_to_gcj02(longitude,latitude)
        js_code = f'createMarker({latitude},{longitude},"{name}");'
        self.mapUpdate_signal.emit(js_code)

    def add_marker_gaode(self, latitude, longitude, name):
        js_code = f'covertWGStoGCJ({latitude},{longitude},"{name}");'
        self.mapUpdate_signal.emit(js_code)
    
    def del_marker(self, name):
        js_code = f'deleteMarker("{name}");'
        self.mapUpdate_signal.emit(js_code)

    def del_allmarkers(self):
        js_code = f'deleteAllMarkers();'
        self.mapUpdate_signal.emit(js_code)
    
    def del_sortedMarkers(self,sortedName:str):
        '''
        按照sortedName删除所有的marker,marker的name为sortedName+*+数字
        '''
        js_code = f'deleteSortedMarkers("{sortedName}");'
        self.mapUpdate_signal.emit(js_code)

    def add_polyline_lat_lon(self, latitudes:list , longitudes:list, color, name):
        #调用add_polyline实现
        paths = []
        for i in range(len(latitudes)):
            paths.append([longitudes[i],latitudes[i]])
        self.add_polyline(paths, color, name)

    def add_polyline(self, paths, color, name, weight= 2 ,opacity =0.5):
        '''
        paths = [[lon,lat],[lon,lat]...]
        '''
        tempPath = []
        for i in range(len(paths)):
            tempPath.append(wgs84_to_gcj02(paths[i][0],paths[i][1]))
        js_code = f'createPolyline({tempPath},"{color}","{name}",{weight},{opacity});'
        self.mapUpdate_signal.emit(js_code)
    
    def add_polyline_tuple_lat_lon(self, paths, color, name, weight= 2 ,opacity =0.5):
        '''
        paths = [(lat,lon),(lat,lon)...]
        '''
        tempPath = []
        for path in paths:
            (lat,lon) = path
            tempPath.append(wgs84_to_gcj02(lon,lat))
        js_code = f'createPolyline({tempPath},"{color}","{name}",{weight},{opacity});'
        self.mapUpdate_signal.emit(js_code)

    def del_polyline(self, name):
        js_code = f'deletePolyline("{name}");'
        self.mapUpdate_signal.emit(js_code)

    def add_UAVMarker(self, latitude, longitude, name):
        longitude,latitude = wgs84_to_gcj02(longitude,latitude)
        js_code = f'createUAVMarker({latitude},{longitude},"{name}");'
        self.mapUpdate_signal.emit(js_code)

    def add_UGVMarker(self, latitude, longitude, name):
        longitude,latitude = wgs84_to_gcj02(longitude,latitude)
        js_code = f'createUGVMarker({latitude},{longitude},"{name}");'
        self.mapUpdate_signal.emit(js_code)
    
    
    def update_UAVMarker(self, latitude, longitude, yaw, name):
        longitude,latitude = wgs84_to_gcj02(longitude,latitude)
        js_code = f'updateUAVMarker({latitude},{longitude},{yaw},"{name}");'
        self.mapUpdate_signal.emit(js_code)

    def update_UGVMarker(self, latitude, longitude, yaw, name):
        longitude,latitude = wgs84_to_gcj02(longitude,latitude)
        js_code = f'updateUGVMarker({latitude},{longitude},{yaw},"{name}");'
        self.mapUpdate_signal.emit(js_code)

    def map_update(self, js_code):
        self.map_view.page().runJavaScript(js_code)

    def append_point_polyline(self,name, point):
        longitude,latitude = wgs84_to_gcj02(point[0],point[1])
        js_code = f'appendPointtoPolyline("{name}",{[longitude,latitude]});'
        self.mapUpdate_signal.emit(js_code)
    
    def showUAVMirrorPosition(self,mirror,basicStatus:sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate):
        GNSS_position = basicStatus.GNSS_position
        try:
            latitude = GNSS_position["latitude"]
            longitude = GNSS_position["longitude"]
        except:
            latitude = GNSS_position[0]
            longitude = GNSS_position[1]
        try:
            vehicle_yaw = basicStatus.vehicle_yaw*180/np.pi
        except:
            vehicle_yaw = 0
            print("vehicle_yaw is not available")  
        for item in self.UAVaddedMarkerID:
            if item == mirror.id:
                self.update_UAVMarker(latitude,longitude,vehicle_yaw,mirror.id)
                self.update_uav_position(mirror, basicStatus)
                return
        if self.mapLoadedFlag == True:
            self.add_UAVMarker(latitude,longitude,mirror.id)
            self.UAVaddedMarkerID.append(mirror.id)  
            self.statusBar_signal.emit(f"mirror:{mirror.id} position:{basicStatus.GNSS_position}")
            self.update_uav_position(mirror, basicStatus)
    
    def showUGVMirrorPosition(self,mirror,basicStatus:sls_UGVmirrorsUpdate.UGVBasicPositionMirrorUpdate):
        GNSS_position = basicStatus.GNSS_position
        if GNSS_position is not None:
            try:
                latitude = GNSS_position["latitude"]
                longitude = GNSS_position["longitude"]
            except:
                latitude = GNSS_position[0]
                longitude = GNSS_position[1]
            vehicle_yaw = basicStatus.vehicle_yaw*180/np.pi
            for item in self.UGVaddedMarkerID:
                if item == mirror.id:
                    self.update_UGVMarker(latitude,longitude,vehicle_yaw,mirror.id)
                    self.update_ugv_position(mirror, basicStatus)
                    return
            if self.mapLoadedFlag == True:
                self.add_UGVMarker(latitude,longitude,mirror.id)
                self.UGVaddedMarkerID.append(mirror.id)
                self.statusBar_signal.emit(f"mirror:{mirror.id} position:{basicStatus.GNSS_position}")
                self.update_ugv_position(mirror, basicStatus)

    def uav_clicked(self,id,button):
        self.statusBar_signal.emit(f"uav clicked:{id}")
        dialog = UAVDialog(self,id,button)
        if "uav1" == id:
            dialog.move(int(self.ScreenWidth * 0.75), self.pos().y())
        elif "uav2" == id:
            dialog.move(int(self.ScreenWidth * 0.75) - 50, self.pos().y() + 50)
        else:
             dialog.move(1100,0)
        dialog.show()

    def ugv_clicked(self,id,button):
        self.statusBar_signal.emit(f"ugv clicked:{id}")
        dialog = UGVDialog(self,id,button)
        dialog.move(int(self.ScreenWidth * 0.75) - 100,self.pos().y() + 100)
        dialog.show()
    
    def uav_pathplan_triggered(self):
        self.statusBar_signal.emit(f"uav path clicked")
        dialog = UAVPPDialog(self,self.ui.pathPlan)
        dialog.move(1200,100)
        dialog.show()

    def ugv_pathplan_triggered(self):
        self.statusBar_signal.emit(f"ugv path clicked")
        dialog = UGVPPDialog(self,self.ui.ugvPathPlan)
        dialog.move(1200,100)
        dialog.show()

    def tools_triggered(self):
        self.statusBar_signal.emit(f"tools clicked")
        dialog = TOOLSDialog(self,self.ui.tools)
        dialog.move(1200,80)
        dialog.show()

    def origin_triggered(self):
        self.statusBar_signal.emit(f"setting origin point")
        dialog = OriginDialog(self)
        dialog.show()

    def ugv_PathUpload_triggered(self):
        self.statusBar_signal.emit(f"ugv path upload")
        dialog = UGVPathUploadDialog(self)
        dialog.show()
    
    def ugv_GPSrectify_triggered(self):
        self.statusBar_signal.emit(f"GPS rectify")
        dialog = GPSRectifyDialog(self)
        dialog.show()

    def serverselection_triggered(self):
        self.statusBar_signal.emit(f"change status")
        dialog = ServerSelectDialog(self)
        dialog.show()       
        
    def switch_location(self, lng, lat):
        """切换地图中心位置"""
        if hasattr(self, 'map_interaction'):
            self.map_interaction.set_map_center(lng, lat)
            self.statusBar_signal.emit(f"地图中心已切换到: 经度{lng}, 纬度{lat}")

    def toggle_chat_window(self):
        dialog = ChatWindow(self)
        chat_x = self.width() - dialog.width() - 20
        chat_y = 20
        chat_height = self.height() - 40
        dialog.setGeometry(chat_x, chat_y, dialog.width(), chat_height)
        dialog.show_animated(self.geometry())

    def init_zoom_widget(self):
        self.zoom_widget = QWidget(self)
        self.zoom_widget.setWindowFlags(Qt.WindowType.Widget | Qt.WindowType.FramelessWindowHint)
        self.zoom_widget.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
        self.zoom_widget.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, False)

        # === 样式 ===
        self.zoom_widget.setStyleSheet("""
            QWidget {
                background-color: rgba(255, 255, 255, 200);
                border-radius: 6px;
                padding: 4px;
            }
            QPushButton {
                min-width: 26px;
                max-width: 26px;
                height: 24px;
                font-size: 12pt;
                border: 1px solid #aaa;
                border-radius: 6px;
                background-color: #fafafa;
            }
            QLabel {
                font-size: 9pt;
                min-width: 45px;
                text-align: center;
            }
        """)

        layout = QHBoxLayout(self.zoom_widget)
        layout.setContentsMargins(8, 4, 8, 4)
        layout.setSpacing(8)

        # === 缩放按钮 + 滑块 ===
        self.zoom_out_btn = QPushButton("－")
        self.zoom_in_btn = QPushButton("＋")
        self.zoom_label = QLabel("200%")

        self.zoom_slider = QSlider(Qt.Orientation.Horizontal)
        self.zoom_slider.setRange(25, 400)
        self.zoom_slider.setValue(200)
        self.zoom_slider.setFixedWidth(160)
        self.zoom_slider.setTickPosition(QSlider.TickPosition.NoTicks)

        layout.addWidget(self.zoom_out_btn)
        layout.addWidget(self.zoom_slider)
        layout.addWidget(self.zoom_in_btn)
        layout.addWidget(self.zoom_label)

        # === 图层按钮 ===
        self.layer_toggle_btn = QPushButton("🟢")
        self.layer_toggle_btn.setToolTip("点击隐藏图层控制")
        self.layer_visible = True

        # === 图标显隐按钮 ===
        self.icon_toggle_btn = QPushButton("👁️")
        self.icon_toggle_btn.setToolTip("点击隐藏所有无人机/无人车图标")
        self.icons_visible = True

        layout.addWidget(self.layer_toggle_btn)
        layout.addWidget(self.icon_toggle_btn)

        # === 信号绑定 ===
        self.zoom_slider.valueChanged.connect(self.update_map_zoom)
        self.zoom_in_btn.clicked.connect(lambda: self.adjust_zoom(20))
        self.zoom_out_btn.clicked.connect(lambda: self.adjust_zoom(-20))
        self.layer_toggle_btn.clicked.connect(self.toggle_layer_control)
        self.icon_toggle_btn.clicked.connect(self.toggle_icons_visibility)

        # === 定位到右下角 ===
        self.zoom_widget.adjustSize()
        w = self.zoom_widget.sizeHint().width()
        h = self.zoom_widget.sizeHint().height()
        margin_right = 16
        margin_bottom = 80
        self.zoom_widget.setGeometry(self.width() - w - margin_right,
                                    self.height() - h - margin_bottom,
                                    w, h)
        self.zoom_widget.raise_()
        self.zoom_widget.show()


    def position_zoom_widget(self):
        if hasattr(self, "zoom_widget"):
            self.zoom_widget.adjustSize()
            w = self.zoom_widget.sizeHint().width()
            h = self.zoom_widget.sizeHint().height()

            margin_right = 16
            margin_bottom = 80
            self.zoom_widget.setGeometry(self.width() - w - margin_right,
                                        self.height() - h - margin_bottom,
                                        w, h)

    #滑动条控制缩放倍率
    def update_map_zoom(self, value):
        zoom_factor = value / 100.0
        if hasattr(self, "map_view"):
            self.map_view.setZoomFactor(zoom_factor)
        if hasattr(self, "zoom_label"):
            self.zoom_label.setText(f"{value}%")
    #按钮控制缩放倍率
    def adjust_zoom(self, delta):
        if hasattr(self, "zoom_slider"):
            current = self.zoom_slider.value()
            new_value = max(25, min(400, current + delta))
            self.zoom_slider.setValue(new_value)
    #窗口大小变化时自动调整缩放控件位置
    def resizeEvent(self, event):
        self.status_btn.move(
        self.contentsRect().right() - 70,
        self.contentsRect().top() 
        )
        super().resizeEvent(event)
        self.position_zoom_widget()

    def toggle_layer_control(self):
        if not hasattr(self, "layer_visible"):
            self.layer_visible = True

        # 翻转状态
        self.layer_visible = not self.layer_visible

        if self.layer_visible:
            # 显示图层控件
            js_code = """
            // 显示常见版本的图层管理控件
            var candidates = ['.amap-layercontrol', '.amap-maptype', '.amap-ctrl-layer', '.amap-ctrl-maptype'];
            candidates.forEach(function(cls) {
                var els = document.querySelectorAll(cls);
                els.forEach(function(e) {
                    e.style.display = 'block';
                });
            });
            """
            self.layer_toggle_btn.setText("🟢")
            self.layer_toggle_btn.setToolTip("点击隐藏图层控件")
        else:
            # 隐藏图层控件
            js_code = """
            // 隐藏常见版本的图层管理控件（只隐藏右上角按钮，不隐藏地图）
            var candidates = ['.amap-layercontrol', '.amap-maptype', '.amap-ctrl-layer', '.amap-ctrl-maptype'];
            candidates.forEach(function(cls) {
                var els = document.querySelectorAll(cls);
                els.forEach(function(e) {
                    e.style.display = 'none';
                });
            });
            """
            self.layer_toggle_btn.setText("🔴")
            self.layer_toggle_btn.setToolTip("点击显示图层控件")

        if hasattr(self, "map_view"):
            self.map_view.page().runJavaScript(js_code)

    def toggle_icons_visibility(self):
        if not hasattr(self, "icons_visible"):
            self.icons_visible = True

        self.icons_visible = not self.icons_visible

        if self.icons_visible:
            js_code = "showAllMarkersWithDots();"
            self.icon_toggle_btn.setText("👁️")
            self.icon_toggle_btn.setToolTip("点击隐藏所有无人机/无人车图标")
        else:
            js_code = "hideAllMarkersWithDots();"
            self.icon_toggle_btn.setText("🚫")
            self.icon_toggle_btn.setToolTip("点击显示所有无人机/无人车图标")

        if hasattr(self, "map_view"):
            self.map_view.page().runJavaScript(js_code)

    def toggle_status_panel(self):
        """展开/收起状态监控面板"""
        panel_width = 200
        panel_top = 50
        full_height = 500  

        if not self.is_expanded:
            self.anim.setDuration(300)
            self.anim.setStartValue(QRect(self.width() - panel_width - 20, panel_top, panel_width, 0))
            self.anim.setEndValue(QRect(self.width() - panel_width - 20, panel_top, panel_width, full_height))
            self.anim.start()
        else:
            self.anim.setDuration(300)
            self.anim.setStartValue(QRect(self.width() - panel_width - 20, panel_top, panel_width, full_height))
            self.anim.setEndValue(QRect(self.width() - panel_width - 20, panel_top, panel_width, 0))
            self.anim.start()
        self.is_expanded = not self.is_expanded



    def update_liquid(self):
        """模拟喷药液剩余量实时变化"""
        new_percent = random.randint(0, 100)
        self.energy_ball.setPercent(new_percent)

    def update_uav_position(self, mirror, basicStatus):
        """由上位机镜像回调更新无人机经纬度与高度"""
        try:
            latitude = basicStatus.GNSS_position["latitude"]
            longitude = basicStatus.GNSS_position["longitude"]
            rel_alt = getattr(basicStatus, "rel_alt", None)  # ✅ 相对高度
            if mirror.id == "uav1":
                self.label_uav1_lat.setText(f"纬度：{latitude:.6f}")
                self.label_uav1_lon.setText(f"经度：{longitude:.6f}")
                if rel_alt is not None:
                    self.label_uav1_yaw.setText(f"高度：{rel_alt:.2f} m")
                else:
                    self.label_uav1_yaw.setText("高度：--")
            elif mirror.id == "uav2":
                self.label_uav2_lat.setText(f"纬度：{latitude:.6f}")
                self.label_uav2_lon.setText(f"经度：{longitude:.6f}")
                if rel_alt is not None:
                    self.label_uav2_yaw.setText(f"高度：{rel_alt:.2f} m")
                else:
                    self.label_uav2_yaw.setText("高度：--")
        except Exception as e:
            print(f"[UAV更新错误] {e}")


    def update_ugv_position(self, mirror, basicStatus:sls_UGVmirrorsUpdate.UGVBasicPositionMirrorUpdate):
        """从镜像更新 UGV 经纬度与航向角"""
        try:
            latitude = basicStatus.GNSS_position["latitude"]
            longitude = basicStatus.GNSS_position["longitude"]
            yaw = getattr(basicStatus, "vehicle_yaw", 0.0)
            self.label_ugv_lat.setText(f"纬度：{latitude:.6f}")
            self.label_ugv_lon.setText(f"经度：{longitude:.6f}")
            self.label_ugv_yaw.setText(f"航向角：{yaw:.1f}°")
        except Exception as e:
            print(f"[UGV update error] {e}")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    # 启动前显示服务器模式选择
    dialog = ServerSelectDialog()
    if dialog.exec() == QDialog.DialogCode.Accepted:
        local_host_mode = dialog.mode                       # 获取选择的模式
        selected_coordinates = dialog.selected_coordinates  # 获取选中的经纬度
        
        main_window = NGCMainWindow(selected_coordinates)
        main_window.local_host_mode = local_host_mode
        main_window.show()
        sys.exit(app.exec())